import pygst
pygst.require("0.10")
import gst
import gobject
from util import device

class MicController( gobject.GObject ):

    __gsignals__ = {
                                
            'my_ssrc' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                    (gobject.TYPE_UINT,))
    }
    
    def __init__(self, bcast_host, port):
        gobject.GObject.__init__( self )

        self._bcast_host = bcast_host
        self._port = port 

        # record to file pipeline
        self._file_pipeline = gst.Pipeline( "FVFileRecord" )
        if device.current() == device.NOKIA_TABLET:
            # Nokia DSP
            self._file_mic_src = gst.element_factory_make("dsppcmsrc", "fv_out_audiosrc")  
        else:
            self._file_mic_src = gst.element_factory_make("alsasrc", "fv_out_audiosrc")
        self._file_pipeline.add(self._file_mic_src)
        
        caps = gst.element_factory_make("capsfilter", "fv_in_capsfilter")
        #caps.set_property("caps", gst.caps_from_string("audio/x-mulaw"))
        caps.set_property( "caps", 
        gst.caps_from_string("audio/x-raw-int, endianness=(int)1234,width=(int)16," \
                         "depth=(int)16,signed=(boolean)true,channels=(int)1," \
                         "rate=(int)8000"))
        
        self._file_pipeline.add(caps)
        
        self._wavenc = gst.element_factory_make("wavenc", "wavencoder")
        self._file_pipeline.add( self._wavenc )
        self._file_out = gst.element_factory_make("filesink", "sink")
        self._file_pipeline.add(self._file_out)
        gst.element_link_many(self._file_mic_src, caps, self._wavenc, self._file_out)
        self._file_bus = self._file_pipeline.get_bus()
        self._file_bus.add_signal_watch()
        self._file_bus.connect( 'message', self._onRecordBusMessage )

        self._net_pipeline = None
        
    def _newNetPipeline(self):
        # record to network pipeline
        self._net_pipeline = gst.Pipeline( "FVNetworkOut")
        if device.current() == device.NOKIA_TABLET:
            # Nokia DSP 
            self._net_mic_src = gst.element_factory_make("dsppcmsrc", "fv_out_audiosrc")  
        else:
            self._net_mic_src = gst.element_factory_make("alsasrc", "fv_out_audiosrc")
        print self._net_mic_src
        self._net_pipeline.add(self._net_mic_src)
        
        self._net_enc = gst.element_factory_make("mulawenc", "fv_out_mulawenc")
        self._net_pipeline.add(self._net_enc)
        
        #netcaps = gst.element_factory_make("capsfilter", "fv_in_capsfilter")
        #netcaps.set_property("caps", gst.caps_from_string("audio/x-mulaw"))
        #gst.caps_from_string("audio/x-raw-int, endianness=(int)1234,width=(int)16," \
        #                 "depth=(int)16,signed=(boolean)true,channels=(int)1," \
        #                 "rate=(int)8000"))
        #mulaw_cap = gst.caps_from_string("audio/x-mulaw")
        
        #self._net_pipeline.add(netcaps)
        
        self._rtp_pay = gst.element_factory_make("rtppcmupay", "payloader")
        self._net_pipeline.add(self._rtp_pay)
        self._rtp_bin = gst.element_factory_make("gstrtpbin", "rtpbin")
        #self._net_pipeline.add(self._rtp_bin)
        self._udp_sink = gst.element_factory_make("udpsink", "udpsink")
        self._udp_sink.set_property("clients", self._bcast_host+":"+str(self._port))
        self._net_pipeline.add(self._udp_sink)
        self._rtcp_sink = gst.element_factory_make("udpsink", "rtcpsink")
        self._rtcp_sink.set_property("clients", self._bcast_host+":"+str(self._port+1))
        #self._net_pipeline.add(self._rtcp_sink)

        #self._net_mic_src.link_pads_filtered( 'src', self._rtp_pay, 'sink', mulaw_cap )
        #self._net_mic_src.link_filtered( self._rtp_pay, netcaps )
        #self._net_mic_src.link( self._rtp_pay )
        #self._rtp_pay.link_pads( 'src', self._rtp_bin, 'send_rtp_sink_0' )
        #self._rtp_bin.link_pads( 'send_rtp_src_0', self._udp_sink, 'sink')
        #self._rtp_bin.link_pads( 'send_rtcp_src_0', self._rtcp_sink, 'sink' )
        #self._rtp_pay.link( self._udp_sink )
        
        gst.element_link_many( self._net_mic_src, self._rtp_pay, self._udp_sink )
        self._net_bus = self._net_pipeline.get_bus()
        self._net_bus.add_signal_watch()
        self._net_bus.connect( 'message', self._onSendNetBusMessage )        
        
    def _onRecordBusMessage(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_EOS:
            self._file_pipeline.set_state(gst.STATE_NULL)
            print "eos"
            # TODO: fix this
            #self.emit('stopped_play', self.currentPlayingID)
        elif t == gst.MESSAGE_ERROR:
            self._file_pipeline.set_state(gst.STATE_NULL)
            print "error:",message
      
    def _onSendNetBusMessage(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_EOS:
            self._net_pipeline.set_state(gst.STATE_NULL)
            print "eos"
            # TODO: fix this
            #self.emit('stopped_play', self.currentPlayingID)
        elif t == gst.MESSAGE_ERROR:
            self._net_pipeline.set_state(gst.STATE_NULL)
            print "error",message
      
    def startRecord( self, filename ):
        self._file_out.set_property('location', filename)
        #self._net_mic_src.set_state(gst.STATE_NULL)
        if self._net_pipeline is not None:
            self._net_pipeline.set_state(gst.STATE_NULL)
        self._file_pipeline.set_state(gst.STATE_PLAYING)

    def stopRecord( self ):
        self._file_pipeline.set_state(gst.STATE_NULL)
        #self._net_pipeline.set_state(gst.STATE_PLAYING)

    def micMute( self ):
        #self._net_mic_src.set_state(gst.STATE_NULL)
        self._net_pipeline.set_state(gst.STATE_NULL)

    def micUnmute( self ):
        self._file_pipeline.set_state(gst.STATE_NULL)
        if self._net_pipeline is not None:
            if self._net_pipeline.get_state()[1] is not gst.STATE_NULL: 
                self._net_pipeline.set_state(gst.STATE_NULL)
        self._newNetPipeline()
        #self._net_mic_src.set_state(gst.STATE_PLAYING)
        self._net_pipeline.set_state(gst.STATE_PLAYING)
        #print "Net pipeline state:",self._net_pipeline.get_state()[0], self._net_pipeline.get_state()[1]
        #if self._net_pipeline.get_state()[1] is not gst.STATE_PLAYING:
        #    print "Net pipepline is starting to play again."
        #    self._net_pipeline.set_state(gst.STATE_PLAYING)
        #rtppad = self._rtp_bin.get_pad( 'send_rtp_src_0' )
        rtppad = self._rtp_pay.get_pad( 'src' )
        self._probe_id = rtppad.add_buffer_probe( self._probe, 'ssrc')
        #rtpcaps = rtppad.proxy_getcaps()
        #print rtpcaps
        
    def _probe(self, pad, data, id):
        """
            Method to find the ssrc generated by this source
            @param data: the audio buffer
            @param id: the id to search for 'ssrc'
        """
        self.emit( 'my_ssrc', int(data.get_caps()[0][id]) )
        pad.remove_buffer_probe( self._probe_id )
        return True
        
gobject.type_register( MicController )

if __name__ == "__main__":
    import time
    
    ain = MicController("18.85.19.255", 30033)
    i = 'g'
    recording = False
    streaming = False
    while i != 'q':
        # n to stream to network or stop stream to network, f to start recording to file or stop recording
        # q to stop
        i = raw_input("n, f or q: ")
        if i is 'f':
            if recording:
                print "Stop recording"
                ain.stopRecord()
                recording = False
            else:
                print "Start recording"
                ain.startRecord('fv'+str(time.time())+".wav")
                recording = True
        if i is 'n':
            if streaming:
                print "Stop streaming"
                ain.micMute()
                streaming = False
            else:
                print "Start streaming"
                ain.micUnmute()
                streaming = True
                

